﻿using Devil;
using GameLogic;
using GameToolkit;
using Steamworks;
using System.Collections;
using System;
using System.Collections.Generic;
using UnityEngine;

public class SteamConfig : PublishConfig, IGameSystem, IUpdateGameCallback, IQuitGameCallback
{
    [SerializeField]
    uint m_AppId;

    [SerializeField]
    bool m_ResetAchievements;

    [SerializeField, Min(2f)]
    float m_ConnectionTimeout = 4f;

    [SerializeField]
    int m_ReconnectionCount = 1;

    [SerializeField, Min(2f)]
    float m_ReconnectionDelay = 3;

    [SerializeField, TableReference("assets/tables/global/keyword.txt@content", PageSize = 20)]
    int m_ErrorTitle;

    [SerializeField, TableReference("assets/tables/global/keyword.txt@content", PageSize = 20)]
    int m_ConnError;


    bool mIsSteamDeck;
    float mSubmitAchDelay;
    bool mIsConnected;
    Connection mConn;

    List<int> mUpdateAchs = new List<int>();

    public override string Title => mIsSteamDeck ? "SteamDeck" : "Steam";

    public override string UsrID => SteamUser.GetSteamID().ToString();

    protected override void OnGetLicence(EVerifyCode result, string msg)
    {
    }

    void IGameSystem.OnInitializationPhase(EInitSystemPhase phase)
    {
        if (phase == EInitSystemPhase.Final)
        {
            SteamManager.sAppId = (AppId_t)m_AppId;
            SteamManager.Initialize();
            //mIsSteamDeck = StringUtil.EqualIgnoreCase(SystemInfo.deviceModel, "Jupiter (Valve)");
            mIsSteamDeck = SteamUtils.IsSteamRunningOnSteamDeck();
            mConn = new Connection(this);
            mConn.OnConnected += OnConnected;
            mConn.ConnectSeriver();
        }
    }

    void IQuitGameCallback.OnQuitGame(ParallelCommandBuffer delayCommands)
    {
        if(mConn != null)
        {
            mConn.Dispose();
            mConn = null;
        }
    }

    private void OnConnected(bool obj)
    {
        mIsConnected = obj;
    }

    [InvokeOnThread(WorkThread =  EThreadTag.SubThread)]
    void IUpdateGameCallback.OnUpdateGame(float deltaTime)
    {
        if (!mIsConnected)
            return;
        if (mSubmitAchDelay > 0)
        {
            mSubmitAchDelay -= deltaTime;
            return;
        }
//        var mgr = AchievementManager.Instance;
//        if (mgr != null && mgr.IsDirty)
//        {
//#if UNITY_EDITOR
//            string errorTag = "update value";
//#endif
//            // unlock success
//            var achievementValueList = new List<AchievementValue>();
//            mgr.GetAchievementValues(achievementValueList);
//            mUpdateAchs.Clear();
//            bool success = true;

//            for (int i = 0; success && i < achievementValueList.Count; i++)
//            {
//                var achiValue = achievementValueList[i];
//                var achievement = TableSet<Achievement>.Instance[achiValue.achId];
//                if (achievement == null || string.IsNullOrEmpty(achievement.arcId))
//                    continue;

//                var progress = achiValue.value;
//                var maxProgress = achievement.progress_value;
//                if (!string.IsNullOrEmpty(achievement.progress_data))
//                {
//                    if (progress >= maxProgress)
//                        success = SteamUserStats.SetAchievement(achievement.arcId);
//                }
//                //if (!string.IsNullOrEmpty(achievement.progress_data) && maxProgress > 1)
//                //    success = SteamUserStats.SetStat(achievement.arcId, progress);
//                else if (progress > 0)
//                    success = SteamUserStats.SetAchievement(achievement.arcId);
//                //else
//                //    success = false;
//                if (success)
//                {
//                    mUpdateAchs.Add(achievement.DataId);
//#if UNITY_EDITOR
//                    Debug.LogFormat("更新成就【{0}】（{1}/{2}）", achievement.arcId, achiValue.value, achievement.progress_value);
//#endif
//                }
//#if UNITY_EDITOR
//                else
//                    errorTag = $"update ach_{achievement.DataId}";
//#endif
//            }
//            if (success)
//            {
//                success = SteamUserStats.StoreStats();
//#if UNITY_EDITOR
//                if (!success)
//                    errorTag = "save value";
//#endif
//            }
//            if (success)
//            {
//                if (achievementValueList.Count == mUpdateAchs.Count)
//                {
//                    mgr.ClearDirtyFlag(true);
//                }
//                else
//                {
//                    mgr.ClearDirtyFlag(false);
//                    for (int i = 0; i < mUpdateAchs.Count; i++)
//                    {
//                        mgr.RemoveAchievementData(mUpdateAchs[i]);
//                    }
//                }
//                mUpdateAchs.Clear();
//            }
//            else
//            {
//#if UNITY_EDITOR
//                Debug.LogError($"更新成就失败({errorTag})");
//#endif
//                mSubmitAchDelay = m_ReconnectionDelay;
//            }
        }



    class Connection : Disposable, IYieldCommand
    {
        //private readonly static TextRef mTitle = new TextRef("错误");
        //private readonly static TextRef mDes = new TextRef("向 Steam 请求统计信息失败。\n是否重新发起请求？");
        //private readonly static TextRef mSubmit = new TextRef("确定");
        //private readonly static TextRef mCancel = new TextRef("取消");

        SteamConfig mCfg;

        const int STAT_START = 0;
        const int STAT_REQUEST = 1;
        const int STAT_FINISHED = 2;
        const int STAT_FAIL = 3;
        int mState;


        public event Action<bool> OnConnected;

        ParallelDispatcher.Handler mConnectProgress;
        public bool IsConnected { get; private set; }

        int mCurrentConnectCount;
        bool mStateValid;

        protected Callback<UserStatsReceived_t> m_UserStatsReceived;

        public Connection(SteamConfig cfg)
        {
            mCfg = cfg;

            m_UserStatsReceived = Callback<UserStatsReceived_t>.Create(OnUserStatsReceived);

            IsConnected = false;
            mStateValid = false;

            mCurrentConnectCount = 0;
        }

        public void ConnectSeriver()
        {
            if (!IsConnected && !mConnectProgress.IsAlive)
                mConnectProgress = ParallelUtils.Schedule(this, false);
        }

        protected override void OnDisposing()
        {
            IsConnected = false;
            mConnectProgress.Abort();
            OnConnected = null;
            m_UserStatsReceived?.Dispose();
            m_UserStatsReceived = null;
        }

        IEnumerator IYieldCommand.Execute()
        {
            //SteamUGC.CreateItem(SteamUtils.GetAppID(), EWorkshopFileType.k_EWorkshopFileTypeCollection);
            IsConnected = false;
            long time = 0;
            while (mState != STAT_FINISHED)
            {
                if (mState == STAT_START)
                {
                    mStateValid = SteamUserStats.RequestCurrentStats();
                    mState = STAT_REQUEST;
                    time = DateTime.UtcNow.Ticks;
                }
                else if (mState == STAT_REQUEST)
                {
                    var secs = (DateTime.UtcNow.Ticks - time) * ParallelDispatcher.tick_2_seconds;
                    if (secs > mCfg.m_ConnectionTimeout || !mStateValid)
                    {
                        mCurrentConnectCount++;
                        if (mCurrentConnectCount < mCfg.m_ReconnectionCount)
                        {
                            mState = STAT_START;
                            yield return new WaitSeconds(mCfg.m_ReconnectionDelay);
                        }
                        else
                        {
                            mState = STAT_FAIL;
                            MainThread.RunOnMainThread(ConnectFailPopup);
                        }
                    }

                }
                else if (mState == STAT_FAIL)
                {

                }
                yield return null;
            }
#if UNITY_EDITOR
            if (mCfg.m_ResetAchievements)
            {
                SteamUserStats.ResetAllStats(true);
            }
#endif
            OnConnected?.Invoke(IsConnected);
            //var dlg = new DefaultDlgRequest("Info", "You're connected to steam successfully.", EDialogOperate.OK, null);
            //MainThread.RunOnMainThread(dlg.Request, "DefaultDialog");
        }

        void ConnectFailPopup()
        {
            SetReconnect(false);
            //var dlg = new DefaultDlgRequest(mCfg.m_ErrorTitle.GetKeyword("错误"),
            //    mCfg.m_ConnError.GetKeyword("与 Steam 链接失败，是否重试？"),
            //    EDialogOperate.Yes, EDialogOperate.No, ResponseReconnect);
            //dlg.Request();
        }

        //void ResponseReconnect(EDialogOperate oper)
        //{
        //    SetReconnect(oper == EDialogOperate.Yes);
        //}

        void SetReconnect(bool isReconnect)
        {
            if (isReconnect)
            {
                mCurrentConnectCount = 0;
                mState = STAT_START;
            }
            else
            {
                mState = STAT_FINISHED;
                IsConnected = false;
            }
        }

        private void OnUserStatsReceived(UserStatsReceived_t param)
        {
            if (mState == STAT_REQUEST)
            {
                if (param.m_eResult == Steamworks.EResult.k_EResultOK || param.m_eResult == Steamworks.EResult.k_EResultFail)
                {
                    mStateValid = true;
                    mState = STAT_FINISHED;
                    IsConnected = true;
                }
                else
                {
                    mStateValid = false;
                }
            }
        }
    }
}

